/*
 * DexClass.h
 *
 *  Created on: 2011-7-18
 *      Author: gexiao
 */
/*
 * Functions to deal with class definition structures in DEX files
 */
#ifndef DEXCLASS_H_
#define DEXCLASS_H_
#include "DexFile.h"
#include "Leb128.h"

//expanded form of a class_data_item header
typedef struct DexClassDataHeader {
	u4 staticFieldsSize;
	u4 instanceFieldsSize;
	u4 directMethodsSize;
	u4 virtualMethodsSize;
} DexClassDataHeader;

//expanded form of encoded_field
typedef struct DexField {
	u4 fieldIdx; //index to a field_id_item
	u4 accessFlags;
} DexField;

//expanded form of encoded_method
typedef struct DexMethod {
	u4 methodIdx; //index to a method_id_item
	u4 accessFlags;
	u4 codeOff; //file offset to a code_item
} DexMethod;

/*
 * expanded form of class_data_item. Note: If a particular item is
 * absent (e.g., no static fields), then the corresponding pointer
 * is set to NULL.
 */
typedef struct DexClassData {
	DexClassDataHeader header;
	DexField* staticFields;
	DexField* instanceFields;
	DexMethod* directMethods;
	DexMethod* virtualMethods;
} DexClassData;

/*
 * Read the header of a class_data_item without verification. This
 * updates the given data pointer to point past the end of the read
 * data.
 */DEX_INLINE void dexReadClassDataHeader(const u1** pData,
		DexClassDataHeader* pHeader) {
	pHeader->staticFieldsSize = readUnsignedLeb128(pData);
	pHeader->instanceFieldsSize = readUnsignedLeb128(pData);
	pHeader->directMethodsSize = readUnsignedLeb128(pData);
	pHeader->virtualMethodsSize = readUnsignedLeb128(pData);
}

/*
 * Read an encode_field without verification. This updates the
 * given data pointer to point past the end of the read data.
 *
 * The lastIndex value should be set to 0 before the first field in
 * a list is read. It is updated as fields are read and used in the
 * decode process.
 */DEX_INLINE void dexReadClassDataField(const u1** pData, DexField* pField,
		u4* lastIndex) {
	u4 index = *lastIndex + readUnsignedLeb128(pData);

	pField->accessFlags = readUnsignedLeb128(pData);
	pField->fieldIdx = index;
	*lastIndex = index;
}

/*
 * Get the DexCode for a DexMethod. Returns NULL if the class is native
 * or abstract.
 */DEX_INLINE const DexCode* dexGetCode(const DexFile* pDexFile,
		const DexMethod* pDexMethod) {
	if (pDexMethod->codeOff == 0)
		return NULL;
	return (const DexCode*) (pDexFile->baseAddr + pDexMethod->codeOff);
}

/*
 * Read an encoded_method without verification. This updates the
 * given data pointer to point past the end of the read data.
 *
 * The lastIndex value should be set to 0 before the first method in
 * a list is read. It is updated as fields are read and used in the
 * decode process.
 */DEX_INLINE void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod,
		u4* lastIndex) {
	u4 index = *lastIndex + readUnsignedLeb128(pData);

	pMethod->accessFlags = readUnsignedLeb128(pData);
	pMethod->codeOff = readUnsignedLeb128(pData);
	pMethod->methodIdx = index;
	*lastIndex = index;
}
#endif /* DEXCLASS_H_ */
